package com.ssy.wireless.util;

import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Created by cofey on 16/11/21.
 */
@Slf4j
public class DateUtils {
    public final static String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public final static String DATE_FORMAT = "yyyy-MM-dd";
    public final static String TIME_FORMAT = "HH:mm:ss";

    /**
     * 将日期按指定格式
     *
     * @param date   日期
     * @param format 格式
     */
    public static String format(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 将日期格式转换为yyyy-MM-dd格式的字符串
     *
     * @param date
     * @return
     */
    public static String formatYMD(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
        return sdf.format(date);
    }

    /**
     * 将日期格式转换为yyyy-MM-dd HH:mm:ss格式的字符串
     *
     * @param date
     * @return
     */
    public static String formatYMDHMS(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
        return sdf.format(date);
    }

    /**
     * 将日期格式转换为HH:mm:ss格式的字符串
     *
     * @param date
     * @return
     */
    public static String formatHMS(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(TIME_FORMAT);
        return sdf.format(date);
    }

    /**
     * 按指定格式将日期字符串转成日期ַ
     *
     * @param str    待转换的日期格式字符串
     * @param format 格式
     */
    public static Date parse(String str, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.parse(str);
        } catch (ParseException e) {
            log.error("转换异常", e);
        }
        return null;
    }

    /**
     * 按 yyyy-MM-dd 的格式将字符串转换成日期
     *
     * @param str 需要转换的日期字符串
     */
    public static Date parseYMD(String str) {
        return parse(str, DATE_FORMAT);
    }

    /**
     * 按 yyyy-MM-dd HH:mm:ss 的格式将字符串转换成日期
     *
     * @param str 需要转换的日期字符串
     */
    public static Date parseYMDHMS(String str) {
        return parse(str, DATE_TIME_FORMAT);
    }

    /**
     * 获取当前时期时间 格式：yyyy-MM-dd HH:mm:ss
     */
    public static String curDateTime() {
        return format(new Date(), DATE_TIME_FORMAT);
    }

    /**
     * 获取当前日期 格式：yyyy-MM-dd
     */
    public static String curDate() {
        return format(new Date(), DATE_FORMAT);
    }

    /**
     * 获取当前时间 格式：HH:mm:ss
     */
    public static String curTime() {
        return format(new Date(), TIME_FORMAT);
    }

    /**
     * 获取当前日期含时分秒
     *
     * @return
     */
    public static final Date getTime() {
        return new Date();
    }

    /**
     * 获取参数日期所在月份第一天
     *
     * @param date
     * @return
     */
    public static final Date getFirstDay(Date date) {
        Calendar timeStamp = Calendar.getInstance();
        timeStamp.setTime(date);
        timeStamp.set(Calendar.DAY_OF_MONTH, 1);
        timeStamp.set(Calendar.HOUR_OF_DAY, 0);
        timeStamp.set(Calendar.MINUTE, 0);
        timeStamp.set(Calendar.SECOND, 0);
        return timeStamp.getTime();
    }

    /**
     * 获取参数日期所在月份最后一天
     *
     * @param date
     * @return
     */
    public static final Date getLastedDay(Date date) {
        Calendar timeStamp = Calendar.getInstance();
        timeStamp.setTime(date);
        timeStamp.set(Calendar.DAY_OF_MONTH, timeStamp.getActualMaximum(Calendar.DATE));
        timeStamp.set(Calendar.HOUR_OF_DAY, 0);
        timeStamp.set(Calendar.MINUTE, 0);
        timeStamp.set(Calendar.SECOND, 0);
        return timeStamp.getTime();
    }

    /**
     * 时间比较，如果两个时间相同，返回真，否则返回假
     *
     * @param date1
     * @param date2
     * @return
     */
    public static final boolean eqCompare(Date date1, Date date2) {
        if (date1.getTime() == date2.getTime()) return true;
        return false;
    }

    /**
     * 时间比较，如果参数date1大于参数date2 ，返回真，否则返回假
     *
     * @param date1
     * @param date2
     * @return
     */
    public static final boolean gtCompare(Date date1, Date date2) {
        if (date1.getTime() > date2.getTime()) return true;
        return false;
    }

    /**
     * 时间比较，如果参数date1小于参数date2 ，返回真，否则返回假
     *
     * @param date1
     * @param date2
     * @return
     */
    public static final boolean ltCompare(Date date1, Date date2) {
        if (date1.getTime() < date2.getTime()) return true;
        return false;
    }

    /**
     * 计算两个日期之间相差的秒数
     *
     * @param date1 较小的日期
     * @param date2 较大的日期
     * @return 相差天数
     */
    public static long secondsBetween(Date date1, Date date2) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
        try {
            date1 = sdf.parse(sdf.format(date1));
            date2 = sdf.parse(sdf.format(date2));
        } catch (ParseException e) {
            return 0;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        long time1 = cal.getTimeInMillis();
        cal.setTime(date2);
        long time2 = cal.getTimeInMillis();
        return (time2 - time1) / 1000;
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param date1 较小的日期
     * @param date2 较大的日期
     * @return 相差天数
     */
    public static int daysBetween(Date date1, Date date2) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            date1 = sdf.parse(sdf.format(date1));
            date2 = sdf.parse(sdf.format(date2));
        } catch (ParseException e) {
            return 0;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        long time1 = cal.getTimeInMillis();
        cal.setTime(date2);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 计算两个日期相差的月份数
     *
     * @param date1 较小的日期
     * @param date2 较大的日期
     * @return 相差的月数
     */
    public static int monthsBetween(Date date1, Date date2) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");

        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        try {
            date1 = sdf.parse(sdf.format(date1));
            date2 = sdf.parse(sdf.format(date2));
        } catch (ParseException e) {
            return 0;
        }
        c1.setTime(date1);
        c2.setTime(date2);
        int year = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);

        //开始日期若小月结束日期
        if (year < 0) {
            year = -year;
            return year * 12 + c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
        }

        return year * 12 + c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
    }

    /**
     * 分钟运算(加)
     *
     * @param date 开始日期
     * @param num  分钟数
     * @return Date
     */
    public static Date minuteAdd(Date date, int num) {
        Calendar endDateCal = Calendar.getInstance();
        endDateCal.setTime(date);
        endDateCal.set(Calendar.MINUTE, endDateCal.get(Calendar.MINUTE) + num);
        return endDateCal.getTime();
    }

    /**
     * 分钟运算(减)
     *
     * @param date 开始日期
     * @param num  分钟数
     * @return Date
     */
    public static Date minuteSubtract(Date date, int num) {
        Calendar endDateCal = Calendar.getInstance();
        endDateCal.setTime(date);
        endDateCal.set(Calendar.MINUTE, endDateCal.get(Calendar.MINUTE) - num);
        return endDateCal.getTime();
    }

    /**
     * 天运算
     *
     * @param date   开始日期
     * @param dayNum 天数
     * @return Date
     */
    public static Date dayAdd(Date date, int dayNum) {
        Calendar endDateCal = Calendar.getInstance();
        endDateCal.setTime(date);
        endDateCal.set(Calendar.DATE, endDateCal.get(Calendar.DATE) + dayNum);
        return endDateCal.getTime();
    }

    /**
     * 月份运算
     *
     * @param date 开始日期
     * @param num  月数
     * @return Date
     */
    public static Date monthAdd(Date date, int num) {
        Calendar endDateCal = Calendar.getInstance();
        endDateCal.setTime(date);
        endDateCal.set(Calendar.MONTH, endDateCal.get(Calendar.MONTH) + num);
        return endDateCal.getTime();
    }

    public static class YearMonthWeekDayHour {
        private int hour;
        private int day;
        private int week;
        private int month;
        private int year;

        public int getHour() {
            return hour;
        }

        public void setHour(int hour) {
            this.hour = hour;
        }

        public int getDay() {
            return day;
        }

        public void setDay(int day) {
            this.day = day;
        }

        public int getWeek() {
            return week;
        }

        public void setWeek(int week) {
            this.week = week;
        }

        public int getMonth() {
            return month;
        }

        public void setMonth(int month) {
            this.month = month;
        }

        public int getYear() {
            return year;
        }

        public void setYear(int year) {
            this.year = year;
        }
    }

    public static YearMonthWeekDayHour getYearMonthWeekDay(Date date) {
        YearMonthWeekDayHour result = new YearMonthWeekDayHour();
        Calendar currentDate = Calendar.getInstance();
        currentDate.setTime(date);
        currentDate.setFirstDayOfWeek(Calendar.MONDAY);
        String dateStr = format(date, "yyyyMMddHH");
        int hour = Integer.valueOf(dateStr);
        int day = Integer.valueOf(dateStr.substring(0, 8));
        int week = currentDate.get(Calendar.WEEK_OF_YEAR);
        int month = Integer.valueOf(dateStr.substring(0, 6));
        int year = Integer.valueOf(dateStr.substring(0, 4));
        result.setHour(hour);
        result.setYear(year);
        result.setMonth(month);
        result.setDay(day);
        //周需要特别计算
        currentDate.add(Calendar.DAY_OF_MONTH, -7);
        week = week < currentDate.get(Calendar.WEEK_OF_YEAR) ? Integer.valueOf((year++) + "" + week) : Integer.valueOf(year + "" + week);
        result.setWeek(week);
        return result;
    }

    public static void main(String[] args) {
        YearMonthWeekDayHour yearMonthWeekDay = getYearMonthWeekDay(parseYMDHMS("2016-12-31 12:10:10"));
        System.out.println(yearMonthWeekDay);
        System.out.println(formatYMDHMS(DateUtils.monthAdd(new Date(), 1)));
        String s = MD5.getInstance().exec("123456");
        System.out.println(s);
        StringBuilder sb = new StringBuilder("2016010211");
        sb.insert(4, "-");
        sb.insert(7, "-");
        sb.insert(10, " ");
        Date parse = DateUtils.parse(sb.toString(), "yyyy-MM-dd HH");
        System.out.println(DateUtils.format(parse, "yyyy-MM-dd HH"));
    }
}
